Getting started

Create a connection to the Barb API

This code uses your account details to get an access token from the API. Your creds.json file should include the email and password supplied by BARB. For example:

{"email": "me@coppelia.io", "password": "INSERT PASSWORD"}
import pybarb as pb
import json
import plotly.io as pio
pio.renderers.default = "plotly_mimetype+notebook"

# Read in Barb API credentials
with open("/Users/simon_business/Documents/disposable/clients/BARB/creds.json") as file:
    creds = json.load(file)

# Create a BarbAPI object and connect
barb_api = pb.BarbAPI(creds)
barb_api.connect()

%load_ext autoreload
%autoreload 2

Querying an endpoint

There are (at present) three endpoint methods: programme_ratings, advertising_spots and audiences_by_time. Query parameters can be supplied as arguments to the function. See the Barb API documentation for the available query parameters.

Example: querying the programme_ratings endpoint

Here we get the audience figures for all programs shown on BBC 1 to the BBC Network panel between 2020-01-01 and 2020-01-03.

bbc_1_progs = barb_api.programme_ratings(min_transmission_date = "2020-01-01", 
                           max_transmission_date = "2020-01-03", 
                           station="BBC1", panel="bbc network", 
                           consolidated=True)

bbc_1_progs.to_dataframe()
panel_region station_name programme_name programme_type programme_start_datetime programme_duration_minutes spans_normal_day uk_premiere broadcaster_premiere programme_repeat episode_number episode_name genre audience_size_hundreds date_of_transmission audience_name audience_target_size_hundreds
0 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 1032 2020-01-02 All Homes 269200
1 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 1243 2020-01-02 All Adults 510930
2 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 740 2020-01-02 All Men 251740
3 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 893 2020-01-02 All Houseperson 269200
4 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 0 2020-01-02 All Children aged 4-15 94570
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
11813 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 0 2020-01-03 Boys 10-12 12300
11814 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 1332 2020-01-03 Adults, Lightest Third 170290
11815 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 190 2020-01-03 Adults, Lightest Sixth 85160
11816 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 865 2020-01-03 ABC1 Adults, Lightest Third 94760
11817 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 71 2020-01-03 Adults 16-34, Lightest Third 47620

11818 rows × 17 columns

To find the right station or panel name you can use the list_stations() and list_panels() methods. You can use any regex string as an argument.

barb_api.list_stations("ITV")
['ITV1',
 'ITV1 HD',
 'ITV1+1',
 'ITV4+1',
 'ITV Play',
 'ITV2+1',
 'ITV3+1',
 'ITV3',
 'ITV4',
 'CITV',
 'ITV Sport',
 'ITV Sport Select',
 'ITV2',
 'ITV2 HD',
 'ITV Encore',
 'ITV Encore +1',
 'ITVBe',
 'ITVBe +1']
barb_api.list_panels("BBC")
['BBC Network',
 'BBC East Region',
 'BBC West Region',
 'BBC South West Region',
 'BBC South Region',
 'BBC Yorkshire & Lincolnshire',
 'BBC North East & Cumbria',
 'BBC North West Region',
 'BBC Scotland Region',
 'BBC Ulster Region',
 'BBC Wales Region',
 'BBC Midlands West',
 'BBC Midlands East',
 'BBC London',
 'BBC South East']

Example: querying the advertising spots endpoint

Here we get all advertising spots placed on ITV 1 by Mediacom Dublin between 2020-01-01 and 2020-01-03.

itv_1_spots = barb_api.advertising_spots("2020-01-01", "2020-01-02", 
                           station="ITV1",  panel="bbc network", 
                           consolidated=True, limit=5000)
itv_1_spots.to_dataframe()
panel_region station_name spot_type spot_start_datetime spot_duration preceding_programme_name succeeding_programme_name break_type position_in_break broadcaster_spot_number ... clearcast_buyer_code clearcast_buyer_name clearcast_advertiser_code clearcast_advertiser_name campaign_approval_id sales_house_name audience_size_hundreds date_of_transmission audience_name audience_target_size_hundreds
0 BBC Network ITV spot 2020-01-01 08:20:34 60 HOTEL TRANSYLVANIA SERIES THE RUBBISH WORLD OF DAVE SPUD end break other 60262703 ... B007161 MEDIALAB GROUP LIMIT A004999 GUIDE DOGS FOR THE B 872780.0 ITV Breakfast 151 2020-01-01 All Homes 269200
1 BBC Network ITV spot 2020-01-01 08:20:34 60 HOTEL TRANSYLVANIA SERIES THE RUBBISH WORLD OF DAVE SPUD end break other 60262703 ... B007161 MEDIALAB GROUP LIMIT A004999 GUIDE DOGS FOR THE B 872780.0 ITV Breakfast 151 2020-01-01 All Adults 510930
2 BBC Network ITV spot 2020-01-01 08:20:34 60 HOTEL TRANSYLVANIA SERIES THE RUBBISH WORLD OF DAVE SPUD end break other 60262703 ... B007161 MEDIALAB GROUP LIMIT A004999 GUIDE DOGS FOR THE B 872780.0 ITV Breakfast 151 2020-01-01 All Houseperson 269200
3 BBC Network ITV spot 2020-01-01 08:20:34 60 HOTEL TRANSYLVANIA SERIES THE RUBBISH WORLD OF DAVE SPUD end break other 60262703 ... B007161 MEDIALAB GROUP LIMIT A004999 GUIDE DOGS FOR THE B 872780.0 ITV Breakfast 151 2020-01-01 Adults 55-64 81070
4 BBC Network ITV spot 2020-01-01 08:37:47 20 THE RUBBISH WORLD OF DAVE SPUD THE RUBBISH WORLD OF DAVE SPUD end break other 60265037 ... B001030 HAVAS MEDIA A004063 DREAMS 868653.0 ITV Breakfast 283 2020-01-01 All Homes 269200
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
3326 BBC Network ITV spot 2020-01-02 09:10:50 10 LORRAINE None centre break other 60243079 ... B005536 MEDIA SAGES LIMITED A015114 INFIRST HEALTHCARE 877162.0 ITV Breakfast 680 2020-01-02 Houseperson working full-time 105330
3327 BBC Network ITV spot 2020-01-02 09:10:50 10 LORRAINE None centre break other 60243079 ... B005536 MEDIA SAGES LIMITED A015114 INFIRST HEALTHCARE 877162.0 ITV Breakfast 143 2020-01-02 Men ABC1 working full-time 87120
3328 BBC Network ITV spot 2020-01-02 09:10:50 10 LORRAINE None centre break other 60243079 ... B005536 MEDIA SAGES LIMITED A015114 INFIRST HEALTHCARE 877162.0 ITV Breakfast 39 2020-01-02 Men AB working full-time 43400
3329 BBC Network ITV spot 2020-01-02 09:10:50 10 LORRAINE None centre break other 60243079 ... B005536 MEDIA SAGES LIMITED A015114 INFIRST HEALTHCARE 877162.0 ITV Breakfast 189 2020-01-02 Houseperson with children 0-15 70140
3330 BBC Network ITV spot 2020-01-02 09:10:50 10 LORRAINE None centre break other 60243079 ... B005536 MEDIA SAGES LIMITED A015114 INFIRST HEALTHCARE 877162.0 ITV Breakfast 35 2020-01-02 Houseperson with children 0-3 25210

3331 rows × 24 columns

We can use the list_buyers and list_advertisers methods to look up the correct names.

barb_api.list_buyers("mediacom")
['essence_mediacom_drt',
 'essence_mediacom_hol',
 'essence_mediacom_nor',
 'essencemediacom',
 'mediacom_dublin',
 'mediacom_holdings_li',
 'mediacom_ireland_(no',
 'mediacom_media_plann',
 'mediacom_north_limit',
 'mediacom_scotland_li']

Example: querying the audiences_by_time endpoint

Here we use the audiences_by_time endpoint to bring back viewing on BBC 1 in 15 minute segments, where the viewing has been on the same day as live (vosdal).

bbc_1_by_time = barb_api.audiences_by_time("2020-01-01", "2020-01-03", time_period_length=15, 
                           viewing_status = 'vosdal',
                           station="BBC1", panel="bbc network")

bbc_1_by_time.to_dataframe()
panel_region station_name date_of_transmission activity transmission_time_period_start audience_size_hundreds audience_name audience_target_size_hundreds
0 BBC Network BBC1 2020-01-01 vosdal 2020-01-01 02:00:00 4018 All Homes 269200
1 BBC Network BBC1 2020-01-01 vosdal 2020-01-01 02:00:00 6964 All Adults 510930
2 BBC Network BBC1 2020-01-01 vosdal 2020-01-01 02:00:00 3494 All Men 251740
3 BBC Network BBC1 2020-01-01 vosdal 2020-01-01 02:00:00 3647 All Houseperson 269200
4 BBC Network BBC1 2020-01-01 vosdal 2020-01-01 02:00:00 234 All Children aged 4-15 94570
... ... ... ... ... ... ... ... ...
15684 BBC Network BBC1 2020-01-03 vosdal 2020-01-04 01:45:00 47 Houseperson with children 0-3 25210
15685 BBC Network BBC1 2020-01-03 vosdal 2020-01-04 01:45:00 157 Adults, Lightest Third 170290
15686 BBC Network BBC1 2020-01-03 vosdal 2020-01-04 01:45:00 74 Adults, Lightest Sixth 85160
15687 BBC Network BBC1 2020-01-03 vosdal 2020-01-04 01:45:00 71 ABC1 Adults, Lightest Third 94760
15688 BBC Network BBC1 2020-01-03 vosdal 2020-01-04 01:45:00 36 Adults 16-34, Lightest Third 47620

15689 rows × 8 columns

Data conversion

The raw json is stored in the api_response_data attribute of the BarbAPI object

However it is much easier to use the various data conversion methods. For example to convert to a data frame we use:

bbc_1_progs.to_dataframe()
panel_region station_name programme_name programme_type programme_start_datetime programme_duration_minutes spans_normal_day uk_premiere broadcaster_premiere programme_repeat episode_number episode_name genre audience_size_hundreds date_of_transmission audience_name audience_target_size_hundreds
0 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 1032 2020-01-02 All Homes 269200
1 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 1243 2020-01-02 All Adults 510930
2 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 740 2020-01-02 All Men 251740
3 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 893 2020-01-02 All Houseperson 269200
4 BBC Network BBC1 Weather for the Week Ahead: Series 2020 programme 2020-01-02 01:50:05 4 False True True False None None None 0 2020-01-02 All Children aged 4-15 94570
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
11813 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 0 2020-01-03 Boys 10-12 12300
11814 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 1332 2020-01-03 Adults, Lightest Third 170290
11815 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 190 2020-01-03 Adults, Lightest Sixth 85160
11816 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 865 2020-01-03 ABC1 Adults, Lightest Third 94760
11817 BBC Network BBC1 BBC London programme 2020-01-03 22:53:27 6 False True True False None None None 71 2020-01-03 Adults 16-34, Lightest Third 47620

11818 rows × 17 columns

You can also use to_csv(), to_excel() and to_json() and to_sql to save to csv files, excel files, json files and to a database.

These can be chained with the query like this

barb_api.programme_ratings("2020-01-01", "2020-01-03", 
                           station="BBC1", panel="bbc network", 
                           consolidated=True).to_excel("programme_ratings.xlsx")

Pivoting the data by audience

For all three endpoints, we can use the audience_pivot() method to produce a dataframe where the audience categories are given in columns. Note the audiences will be summed in each cell.

barb_api.advertising_spots("2020-01-01", "2020-01-02", 
                           station="ITV1", panel="bbc network", 
                           consolidated=True, limit=5000).audience_pivot()
audience_name ABC1 Adults, Lightest Third Adults 16-24 Adults 16-34 Adults 16-34, Lightest Third Adults 35-44 Adults 45-49 Adults 45-54 Adults 55-64 Adults AB Adults ABC1 ... Men AB Men AB working full-time Men ABC1 Men ABC1 16-24 Men ABC1 16-34 Men ABC1 16-44 Men ABC1 35-54 Men ABC1 working full-time Men C2 Men working full-time
panel_region station_name date_of_transmission clearcast_commercial_title
BBC Network ITV 2020-01-01 30 Tuesday clocked 0.0 0.0 0.0 0.0 14.0 0.0 0.0 151.0 0.0 14.0 ... 0.0 0.0 14.0 0.0 0.0 14.0 14.0 14.0 0.0 14.0
30AWC2Grand Sofa CaperGrand SaleNow o 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 65.0 114.0 ... 65.0 0.0 65.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
BEPD Ends Tues 10D 9.0 196.0 377.0 196.0 127.0 0.0 400.0 0.0 217.0 373.0 ... 96.0 96.0 157.0 0.0 96.0 110.0 44.0 110.0 471.0 384.0
BEPD Ends Tues 20A 0.0 0.0 0.0 0.0 14.0 0.0 0.0 179.0 52.0 240.0 ... 0.0 0.0 108.0 0.0 0.0 14.0 14.0 14.0 0.0 14.0
BEPD Ends Tues 20B 0.0 0.0 0.0 0.0 0.0 0.0 0.0 190.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 43.0 0.0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
2020-01-02 Tails Lorraine Collab 30 132.0 84.0 132.0 132.0 553.0 410.0 714.0 881.0 113.0 1266.0 ... 84.0 0.0 334.0 84.0 84.0 84.0 0.0 54.0 165.0 359.0
Virgin Holidays Peak Sale Couples 69.0 0.0 50.0 0.0 521.0 113.0 500.0 1241.0 238.0 1375.0 ... 120.0 120.0 427.0 0.0 0.0 120.0 187.0 187.0 343.0 682.0
Week 14 From Boxing Day Biggest ever sale 0.0 0.0 147.0 0.0 338.0 147.0 491.0 1012.0 73.0 1272.0 ... 0.0 0.0 359.0 0.0 41.0 41.0 67.0 254.0 53.0 413.0
Wonder 2019 10 69.0 0.0 135.0 0.0 1371.0 581.0 1796.0 3065.0 472.0 3729.0 ... 144.0 144.0 965.0 0.0 0.0 144.0 345.0 491.0 703.0 1363.0
myWW TVC 30 alternative intro same o 132.0 84.0 132.0 132.0 591.0 410.0 714.0 942.0 150.0 1304.0 ... 121.0 37.0 371.0 84.0 84.0 121.0 37.0 91.0 200.0 431.0

90 rows × 55 columns

Time series plots

Interactive time series plots are available on all three endpoints.

barb_api.audiences_by_time("2020-01-01", "2020-01-31", time_period_length=15, viewing_status = 'vosdal',
                           station="BBC1", panel="bbc network").ts_plot()

Querying viewing data using the asynchronous API

We would like one day’s worth of viewing data (2023-07-06) for BBC1 East viewing station and the BBC East Region panel.

First we need to look up the viewing station and panels to check we have the correct query parameters

barb_api.list_panels("BBC")
['BBC Network',
 'BBC East Region',
 'BBC West Region',
 'BBC South West Region',
 'BBC South Region',
 'BBC Yorkshire & Lincolnshire',
 'BBC North East & Cumbria',
 'BBC North West Region',
 'BBC Scotland Region',
 'BBC Ulster Region',
 'BBC Wales Region',
 'BBC Midlands West',
 'BBC Midlands East',
 'BBC London',
 'BBC South East']
barb_api.list_viewing_stations("BBC1")
['BBC1 Midlands West',
 'BBC1 East',
 'BBC1 West',
 'BBC1 South West',
 'BBC1 South',
 'BBC1 Yorks/Lincs',
 'BBC1 North East/Cumbria',
 'BBC1 North West',
 'BBC1 Scotland',
 'BBC1 Wales',
 'BBC1 Northern Ireland',
 'BBC1 Midlands East',
 'BBC1 London',
 'BBC1 South East']

Next we need to request the data sets from the asynchronous API. We will use the pybarb package to do this.

barb_api.viewing(min_session_date="2023-07-06", max_session_date="2023-07-06", 
                 viewing_station="BBC1 East", panel="BBC East Region")
Job successfully started. The job id is b0a71da8-9701-4cd4-ae55-8f9f034e5177

Once the job has started we can use the ping_job_status method to check the status of the job. It will check the status every 60 seconds until the job is complete.

barb_api.ping_job_status()
Job not ready yet. Sleeping for 60 seconds.
Job not ready yet. Sleeping for 60 seconds.
Job complete. 1 files are ready for download.

Now we can download the data using the get_asynch_files method.

viewing_results_set = barb_api.get_asynch_files()

In its raw form we can see many of the cells contain json. We will need to unpack this.

viewing_results_set.api_response_data.head(5)
STANDARD_DATE_OF_ACTIVITY SESSION_START SESSION_END HOUSEHOLD DEVICE PANEL_VIEWERS GUEST_VIEWERS PROGRAMMES_VIEWED SPOTS_VIEWED VIEWING_STATION ... PLATFORM ACTIVITY_TYPE CONTENT_ASSET_ITEM_OFFSET PLAYBACK_TYPE SKY_ULTRA_HD START_OF_RECORDING TARGETED_PROMOTION VOD_INDICATOR VOD_PROVIDER REPLICATE_ID
0 2023-07-06 {'barb_polling_datetime': '2023-07-06 03:45:00... {'barb_polling_datetime': '2023-07-06 04:46:00... {'bbc_itv_segment': 'bbc east / east of englan... {'date_valid_for': '2023-07-06', 'device_numbe... [{'date_of_birth': '1990-08-01', 'dependency_o... {} [{'broadcaster_premier': True, 'broadcaster_tr... [] {'viewing_station_code': 32, 'viewing_station_... ... digital terrestrial live viewing (excl targeted advertising) 0 unknown False {} False not on-demand {'vod_provider': 'unknown', 'vod_service': 'un... None
1 2023-07-06 {'barb_polling_datetime': '2023-07-06 18:04:00... {'barb_polling_datetime': '2023-07-06 18:07:00... {'bbc_itv_segment': 'bbc east / east of englan... {'date_valid_for': '2023-07-06', 'device_numbe... [{'date_of_birth': '1948-10-01', 'dependency_o... {'female_45_64': 1, 'male_45_64': 1} [{'broadcaster_premier': True, 'broadcaster_tr... [] {'viewing_station_code': 32, 'viewing_station_... ... digital terrestrial live viewing (excl targeted advertising) 0 unknown False {} False not on-demand {'vod_provider': 'unknown', 'vod_service': 'un... None
2 2023-07-06 {'barb_polling_datetime': '2023-07-06 20:55:00... {'barb_polling_datetime': '2023-07-06 22:45:00... {'bbc_itv_segment': 'bbc east / east of englan... {'date_valid_for': '2023-07-06', 'device_numbe... [{'date_of_birth': '1947-04-01', 'dependency_o... {} [{'broadcaster_premier': True, 'broadcaster_tr... [] {'viewing_station_code': 32, 'viewing_station_... ... digital terrestrial live viewing (excl targeted advertising) 0 unknown False {} False not on-demand {'vod_provider': 'unknown', 'vod_service': 'un... None
3 2023-07-06 {'barb_polling_datetime': '2023-07-06 06:07:00... {'barb_polling_datetime': '2023-07-06 08:18:00... {'bbc_itv_segment': 'bbc east / east of englan... {'date_valid_for': '2023-07-06', 'device_numbe... [{'date_of_birth': '1948-05-01', 'dependency_o... {} [{'broadcaster_premier': True, 'broadcaster_tr... [] {'viewing_station_code': 32, 'viewing_station_... ... digital satellite live viewing (excl targeted advertising) 0 unknown False {} False not on-demand {'vod_provider': 'unknown', 'vod_service': 'un... None
4 2023-07-06 {'barb_polling_datetime': '2023-07-06 21:59:00... {'barb_polling_datetime': '2023-07-06 22:02:00... {'bbc_itv_segment': 'bbc east / east of englan... {'date_valid_for': '2023-07-06', 'device_numbe... [{'date_of_birth': '1948-05-01', 'dependency_o... {} [{'broadcaster_premier': True, 'broadcaster_tr... [] {'viewing_station_code': 32, 'viewing_station_... ... digital satellite live viewing (excl targeted advertising) 0 unknown False {} False not on-demand {'vod_provider': 'unknown', 'vod_service': 'un... None

5 rows × 21 columns

We can either save it as json using the to_json method…

viewing_results_set.to_json("results.json")

Or we can use the to_dataframe method to reshape the data so that we have one row per viewer per programme.

df = viewing_results_set.to_dataframe(unpack=["viewers", "programmes"])
df.head()
programme_start_datetime programme_name date_of_birth dependency_of_children disability ethnic_origin gaelic_language household_status life_stage marital_status ... number_of_tv_sets number_of_vcrs panel_membership_status presence_of_children replication_factor social_class welsh_speaking_home device_number device_on_panel device_type
0 2023-07-06 01:33:57 Joins BBC News: Series 2023 1990-08-01 unclassified no white british not gaelic speaking/not in scotland neither houseperson nor head of household single no children with parents aged 16-34 single / divorced / separated ... 2 0 home on panel (valid reporter) no children 24 D non welsh speaking 2 True tv
4 2023-07-06 18:00:03 BBC News at Six: Series 2023 1948-10-01 unclassified yes limited a little white british not gaelic speaking/not in scotland houseperson and not Head of household couple no children aged 55+ married / living as married ... 1 0 home on panel (valid reporter) no children 21 AB non welsh speaking 1 True tv
8 2023-07-06 18:59:42 Wimbledon: Series 2023 1947-04-01 unclassified no white british not gaelic speaking/not in scotland both houseperson and head of household single no children on own aged 55+ single / divorced / separated ... 1 0 home on panel (valid reporter) no children 8 AB non welsh speaking 1 True tv
12 2023-07-06 06:00:00 Breakfast: Series 2023 1948-05-01 unclassified no white british not gaelic speaking/not in scotland both houseperson and head of household single no children on own aged 55+ single / divorced / separated ... 2 0 home on panel (valid reporter) no children 5 C1 non welsh speaking 1 True tv
16 2023-07-06 18:59:42 Wimbledon: Series 2023 1948-05-01 unclassified no white british not gaelic speaking/not in scotland both houseperson and head of household single no children on own aged 55+ single / divorced / separated ... 2 0 home on panel (valid reporter) no children 5 C1 non welsh speaking 1 True tv

5 rows × 43 columns